package com.mall.util.distributed.raft;

import com.alipay.remoting.rpc.RpcClient;
import com.alipay.remoting.rpc.RpcServer;
import com.mall.util.distributed.raft.config.RaftConfig;
import com.mall.util.distributed.raft.consensus.Consensus;
import com.mall.util.distributed.raft.consensus.DefaultConsensus;
import com.mall.util.distributed.raft.election.ElectionTask;
import com.mall.util.distributed.raft.heartbeat.HeaderBeatTask;
import com.mall.util.distributed.raft.lifecycle.Lifecycle;
import com.mall.util.distributed.raft.lifecycle.LifecycleManager;
import com.mall.util.distributed.raft.node.Node;
import com.mall.util.distributed.raft.pool.RaftThreadPool;
import com.mall.util.distributed.raft.rpc.*;
import lombok.var;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import java.net.URI;

@EnableConfigurationProperties(RaftConfig.class)
public class RaftAutoConfiguration {

    /* core start class */
    @Bean
    public RaftServerBootstrap raftBootstrap() {
        return new RaftServerBootstrap();
    }

    @Bean
    public HeaderBeatTask headerBeatTask() {
        return new HeaderBeatTask(RaftThreadPool.getThreadPool());
    }

    /* election leader class */
    @Bean
    public ElectionTask electionTask() {
        return new ElectionTask(RaftThreadPool.getThreadPool());
    }

    @Bean
    public Lifecycle lifecycle() {
        return new LifecycleManager();
    }

    @Bean
    @ConditionalOnMissingBean(name = "consensus")
    public Consensus consensus() {
        return new DefaultConsensus();
    }

    /*----------------------------------------------RPC----------------------------------------------*/
    /* 初始化raft客户端 */
    @Bean
    @ConditionalOnMissingBean(name = "rpcClient")
    public RaftClient raftClient() {
        var rpcClient = new RpcClient();
        rpcClient.init();

        return new DefaultRaftClient(rpcClient);
    }

    /* 初始化raft服务端 */
    @Bean
    @ConditionalOnMissingBean(name = "rpcServer")
    public RaftServer raftServer(RaftConfig raftConfig) {
        var node = URI.create(raftConfig.getAddress());
        var rpcServer = new RpcServer(node.getPort(), false, false);

        return new DefaultRaftServer(rpcServer);
    }
}
